package com.qianyanglong.zhibo.client.service.impl;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import org.bytedeco.ffmpeg.avcodec.AVPacket;
import org.bytedeco.ffmpeg.avcodec.AVPacketSideData;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegFrameRecorder.Exception;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.bytedeco.opencv.global.opencv_core;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.Videoio;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.qianyanglong.zhibo.client.panel.CapturePanel;
import com.qianyanglong.zhibo.client.service.CameraService;

public class CameraServiceImpl implements CameraService{
	
	private static final Logger logger = LoggerFactory.getLogger(CameraServiceImpl.class);
	
	private Map<String,Integer> map;
	
	private CapturePanel capturePanel;
	
	private VideoCapture videoCapture;
	
	public CameraServiceImpl(CapturePanel capturePanel, Map<String,Integer> map) {
		this.map = map;
		this.capturePanel = capturePanel;
	}

	@Override
	public boolean start() {
		if(videoCapture==null) {
			videoCapture = new VideoCapture();
		}
		map.put("status", 1);
		videoCapture.open(0);
		double w = videoCapture.get(3);
		double h = videoCapture.get(4);
		System.out.println(w+":"+h);
		logger.debug("摄像头是否已开：{}"+videoCapture.isOpened());
		String rtmpURI = "rtmp://192.168.2.200:1935/myapp/test";
		int width = (int)w, height =(int)h, sampleRate = 44100, channels = 2;
		FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtmpURI, width, height, 0);
		// Video
		//recorder.setInterleaved(true);
		recorder.setVideoOption("tune", "zerolatency");
		recorder.setVideoOption("preset", "ultrafast");
		recorder.setVideoOption("crf", "28");
		recorder.setVideoBitrate(2000000);
		// H.264
		recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
		recorder.setFormat("flv");
		recorder.setFrameRate(30);
//		recorder.setGopSize(25 * 2);
		// Audio
//		recorder.setAudioOption("crf", "0");
//		recorder.setAudioQuality(0);
//		recorder.setAudioBitrate(192000);
//		recorder.setSampleRate(sampleRate);
//		recorder.setAudioChannels(channels);
		// AAC
		recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
		Map<String,Long> timstampMap = new HashMap<String, Long>();
		timstampMap.put("videoTS",0L);
		timstampMap.put("startTS",0L);
		try {
			recorder.start();
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
			return false;
		}
		Java2DFrameConverter java2dConverter = new Java2DFrameConverter(); 
		Thread t = new Thread(new Runnable() {
			
			@Override
			public void run() {
				int s = 0;
				int sm = 0;
				while(true) {
					Integer status = map.get("status");
					
					
					logger.debug("当前状态:{}",status);
					if(status==2) {
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						continue;
					}else if(status==3) {
						break;
					}
					Mat frame = new Mat();
					videoCapture.read(frame);
					if(frame.cols()==0||frame.rows()==0||frame.elemSize()==0L) {
						continue;
					}
					logger.debug("图形数据1:{}",frame);
					OpenCVFrameConverter.ToIplImage toIplImage = new OpenCVFrameConverter.ToIplImage();
					Frame convert = toIplImage.convert(frame);
					//Mat frame2 = new Mat();
					//Imgproc.cvtColor(frame, frame2, Imgproc.COLOR_BGRA2RGB);
					
					BufferedImage image = capturePanel.mat2Image(frame);
					capturePanel.image(image);
					capturePanel.repaint();

//					System.out.println("战斗开始");
					long videoTS = timstampMap.get("videoTS");
					long startTS = timstampMap.get("startTS");
					//System.out.println("videoTS："+videoTS);
					if (startTS == 0) {
						startTS = System.currentTimeMillis();
						timstampMap.put("startTS",startTS);
					}
					videoTS = 1000 * (System.currentTimeMillis() - startTS);
					timstampMap.put("videoTS",videoTS);
					
					if (videoTS > recorder.getTimestamp()&&convert!=null&&convert.image.length>0) {
						//System.out.println("videoTS:"+videoTS);
						recorder.setTimestamp(videoTS);
						try {
							//System.out.println("战斗结束1");
							recorder.record(convert);
							//recorder.flush();
							System.out.println("战斗结束2:"+sm);
//							sm++;
//							if(sm==20) {
//								//recorder.flush();
//								//sm = 0;
//							}
						} catch (Exception e) {
							// TODO 自动生成的 catch 块
							e.printStackTrace();
						}
					}
					//System.out.println("战斗结束");
//					Thread t = new Thread(new Runnable() {
//						
//						@Override
//						public void run() {
//
//						}
//					});
//					t.start();
				}
				videoCapture.release();
//				try {
//					recorder.close();
//				} catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
//					// TODO 自动生成的 catch 块
//					e.printStackTrace();
//				}
			}
		});
		t.start();
		return true;
	}

	@Override
	public boolean pause() {
		logger.debug("暂停");
		map.put("status", 2);
		return true;
	}

	@Override
	public boolean stop() {
		logger.debug("停止");
		map.put("status", 3);
		return true;
	}
	
	public Map<String,Integer> getMap(){
		return this.map;
	}

	@Override
	public boolean show() {
		Thread t = new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					Thread.sleep(10000L);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("第1步");
//				String inputPath = "http://192.168.2.200:9080/rtmpLive?port=1935&app=myapp&stream=test";
				String inputPath = "rtmp://192.168.2.200:1935/myapp/test";
				FFmpegFrameGrabber grabber = null;
				try {
					grabber = FFmpegFrameGrabber.createDefault(inputPath);
				} catch (org.bytedeco.javacv.FFmpegFrameGrabber.Exception e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
					return;
				}//"D:\\yN6jj3LAI68A.mp4"
				System.out.println("第2步");
				grabber.setOption("rtsp_transport", "tcp");

				grabber.setImageWidth(960);

				grabber.setImageHeight(540);

				//开启采集器
				System.out.println("第3步");
				try {
					grabber.start();
				} catch (org.bytedeco.javacv.FFmpegFrameGrabber.Exception e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				double frameRate = grabber.getFrameRate();
				System.out.println("第4步");
				//直播播放窗口

				CanvasFrame canvasFrame = new CanvasFrame("悄摸直播——来自"+inputPath);

				canvasFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

				canvasFrame.setAlwaysOnTop(true);

				OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();

				//播流
				System.out.println("第5步");
				
				while (true){
					System.out.println("第6步");
					
					Frame frame = null;
					try {
						frame = grabber.grabImage();
					} catch (org.bytedeco.javacv.FFmpegFrameGrabber.Exception e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					} //拉流
					if(frame!=null) {
						//org.bytedeco.opencv.opencv_core.Mat mat = converter.convertToMat(frame);
						System.out.println("第7步:"+frameRate);
						canvasFrame.showImage(frame); //播放
					}
				}
			}
		});
		t.start();
		return false;
	}

	@Override
	public boolean test() {
		Thread t = new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				FFmpegFrameGrabber g = new FFmpegFrameGrabber(new File("G:/旧/视频/奔跑吧/奔跑吧兄弟 141010_高清.mp4"));
				try {
					g.start();
				} catch (org.bytedeco.javacv.FFmpegFrameGrabber.Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				String rtmpURI = "rtmp://192.168.2.200:1935/myapp/test";
				int width = g.getImageWidth();
				int height =g.getImageHeight();
				double frameRate = g.getFrameRate();
				int sampleRate = g.getSampleRate(); 
				int channels = g.getAudioChannels();
				FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtmpURI, width, height, 0);
				// Video
				recorder.setInterleaved(true);
				recorder.setVideoOption("tune", "zerolatency");
				recorder.setVideoOption("preset", "ultrafast");
				recorder.setVideoOption("crf", "28");
				recorder.setVideoBitrate(2000000);
				// H.264
				recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
				recorder.setFormat("flv");
				recorder.setFrameRate(30);
				recorder.setGopSize(25 * 2);
				// Audio
				recorder.setAudioOption("crf", "0");
				recorder.setAudioQuality(0);
				recorder.setAudioBitrate(192000);
				recorder.setSampleRate(sampleRate);
				recorder.setAudioChannels(channels);
				// AAC
				recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
				try {
					recorder.start();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				try {
					Frame grabFrame =null;
					long timestamp = 0L;
					
					while ((grabFrame = g.grabFrame()) != null) {
						System.out.println("正在推送:"+grabFrame.timestamp);
						//AVPacketSideData avPacketSideData = packet.side_data();
						long s = grabFrame.timestamp;
						timestamp = timestamp+s;
						
						recorder.setTimestamp(timestamp);
						recorder.record(grabFrame);
						//recorder.flush();
						try {
							Thread.sleep(s);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				} catch (org.bytedeco.javacv.FFmpegFrameGrabber.Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				try {
					g.close();
				} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				try {
					recorder.close();
				} catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		t.start();
		
		return false;
	}

}
